package com.open.thinks.todo.system.common;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.open.thinks.todo.system.domain.helper.EnumContentable;
import com.open.thinks.todo.system.domain.helper.TaskPriority;
import com.open.thinks.todo.system.domain.helper.TaskRemider;
import com.open.thinks.todo.system.domain.helper.TaskStatus;
import com.open.thinks.todo.system.domain.helper.TaskType;

public class EnumContentHolder {

	private final static Entries ENTRIES = new Entries();

	static {
		// TaskStatus
		register(TaskStatus.NOT_STARTED, "Not Started");
		register(TaskStatus.IN_PROGRESS, "In Progress");
		register(TaskStatus.COMPLETED, "Completed");
		register(TaskStatus.WATING_ON_SOMEONE_ELSE, "Waiting on someone else");
		register(TaskStatus.DEFERRED, "Deferred");
		// TaskType
		register(TaskType.PRIVATE, "Private");
		register(TaskType.PUBLIC, "Public");
		// TaskPriority
		register(TaskPriority.LOW, "Low");
		register(TaskPriority.NORMAL, "Normal");
		register(TaskPriority.HIGH, "High");
		//TaskRemider
		register(TaskRemider.NO, "No");
		register(TaskRemider.YES, "Yes");
	}

	public static void register(EnumContentable enumObject, String content) {
		ENTRIES.register(enumObject, content);
	}

	public static String getContent(EnumContentable enumObject) {
		return ENTRIES.getContent(enumObject);
	}

	@SuppressWarnings("unchecked")
	public static <T extends EnumContentable> T valueOf(String content,
			Class<? extends EnumContentable> enumContentableType) {
		return (T) ENTRIES.getEnum(content, enumContentableType);
	}

	static class Entries {
		private final Map<Class<? extends EnumContentable>, InnerEntry> enumClassMapping = new ConcurrentHashMap<Class<? extends EnumContentable>, InnerEntry>();

		void register(EnumContentable enumObject, String content) {
			InnerEntry inner = enumClassMapping.get(enumObject.getClass());
			if (inner == null) {
				inner = new InnerEntry();
				inner.register(enumObject, content);
				enumClassMapping.put(enumObject.getClass(), inner);
			}
			inner.register(enumObject, content);
		}

		String getContent(EnumContentable enumObject) {
			InnerEntry inner = getInnerEntry(enumObject.getClass());
			if (inner == null) {
				inner = new InnerEntry();
				inner.register(enumObject, enumObject.toString());
				enumClassMapping.put(enumObject.getClass(), inner);
			}
			return inner.getContent(enumObject);
		}

		EnumContentable getEnum(String content, Class<? extends EnumContentable> enumContentableType) {
			InnerEntry inner = getInnerEntry(enumContentableType);
			if (inner == null) {
				return null;
			}
			return inner.getEnum(content);
		}

		InnerEntry getInnerEntry(Class<? extends EnumContentable> enumContentableType) {
			InnerEntry inner = enumClassMapping.get(enumContentableType);
			return inner;
		}

		class InnerEntry {
			private final Map<EnumContentable, String> enumContentMapping = new ConcurrentHashMap<EnumContentable, String>();
			private final Map<String, EnumContentable> contentEnumMapping = new ConcurrentHashMap<String, EnumContentable>();

			String getContent(EnumContentable enumObject) {
				return enumContentMapping.get(enumObject);
			}

			EnumContentable getEnum(String content) {
				return contentEnumMapping.get(content);
			}

			void register(EnumContentable enumObject, String content) {
				enumContentMapping.put(enumObject, content);
				contentEnumMapping.put(content, enumObject);
			}

		}

	}

}
